from flask import Blueprint, request
from flask_jwt_extended import jwt_required, get_jwt_identity
from app import db
from app.models import Exam, ExamRecord, Question, QuestionCategory
from app.utils.response import success_response, error_response, paginated_response
from app.utils.decorators import admin_required, user_required
from app.models.operation_log import OperationLog
from datetime import datetime
from loguru import logger

exams_bp = Blueprint('exams', __name__)

@exams_bp.route('/', methods=['GET'])
@jwt_required()
def get_exams():
    """获取试卷列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        
        pagination = Exam.query.filter_by(is_active=True).order_by(Exam.created_at.desc()).paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )
        
        exams = [exam.to_dict() for exam in pagination.items]
        
        return paginated_response(
            exams,
            page,
            per_page,
            pagination.total
        )
    except Exception as e:
        logger.error(f"获取试卷列表失败: {e}")
        return error_response('获取试卷列表失败', 500)

@exams_bp.route('/<int:exam_id>', methods=['GET'])
@jwt_required()
def get_exam_detail(exam_id):
    """获取考试详情"""
    try:
        exam = Exam.query.filter_by(id=exam_id, is_active=True).first()
        if not exam:
            return error_response('考试不存在', 404)
        
        return success_response(exam.to_dict())
    except Exception as e:
        logger.error(f"获取考试详情失败: {e}")
        return error_response('获取考试详情失败', 500)

@exams_bp.route('/<int:exam_id>/check-participation', methods=['GET'])
@jwt_required()
def check_participation(exam_id):
    """检查用户是否参与过考试"""
    try:
        current_user_id = get_jwt_identity()
        
        # 检查是否已参与过考试
        exam_record = ExamRecord.query.filter_by(
            user_id=current_user_id,
            exam_id=exam_id
        ).first()
        
        has_participated = exam_record is not None
        
        return success_response({
            'has_participated': has_participated,
            'latest_record': exam_record.to_dict() if exam_record else None
        })
    except Exception as e:
        logger.error(f"检查考试参与状态失败: {e}")
        return error_response('检查失败', 500)

@exams_bp.route('/<int:exam_id>/records', methods=['GET'])
@jwt_required()
def get_exam_records(exam_id):
    """获取用户的考试记录"""
    try:
        current_user_id = get_jwt_identity()
        
        records = ExamRecord.query.filter_by(
            user_id=current_user_id,
            exam_id=exam_id
        ).order_by(ExamRecord.created_at.desc()).all()
        
        return success_response([record.to_dict() for record in records])
    except Exception as e:
        logger.error(f"获取考试记录失败: {e}")
        return error_response('获取考试记录失败', 500)

@exams_bp.route('/<int:exam_id>/questions', methods=['GET'])
@jwt_required()
def get_exam_questions_for_taking(exam_id):
    """获取考试题目（用于考试进行中）"""
    try:
        current_user_id = get_jwt_identity()
        
        # 检查是否有进行中的考试
        exam_record = ExamRecord.query.filter_by(
            user_id=current_user_id,
            exam_id=exam_id,
            end_time=None
        ).first()
        
        if not exam_record:
            return error_response('没有进行中的考试', 400)
        
        exam = exam_record.exam
        questions = exam.get_questions_for_exam()
        
        # 计算剩余时间
        elapsed_time = (datetime.utcnow() - exam_record.start_time).total_seconds()
        remaining_time = max(0, exam.time_limit * 60 - elapsed_time)
        
        return success_response({
            'exam': exam.to_dict(),
            'questions': questions,
            'remaining_time': int(remaining_time)
        })
    except Exception as e:
        logger.error(f"获取考试题目失败: {e}")
        return error_response('获取考试题目失败', 500)

@exams_bp.route('/result/<int:record_id>', methods=['GET'])
@jwt_required()
def get_exam_result(record_id):
    """获取考试结果详情"""
    try:
        current_user_id = get_jwt_identity()
        
        exam_record = ExamRecord.query.filter_by(
            id=record_id,
            user_id=current_user_id
        ).first()
        
        if not exam_record:
            return error_response('考试记录不存在', 404)
        
        # 获取详细的答题情况
        exam = exam_record.exam
        questions_detail = []
        
        for eq in exam.exam_questions:
            question = eq.question
            user_answer = exam_record.answers.get(str(question.id)) if exam_record.answers else None
            is_correct = question.check_answer(user_answer) if user_answer else False
            
            question_detail = {
                'id': question.id,
                'title': question.title,
                'type': question.type,
                'content': question.content,
                'options': question.options,
                'user_answer': user_answer,
                'correct_answer': question.correct_answer,
                'is_correct': is_correct,
                'score': eq.score if is_correct else 0,
                'explanation': question.explanation
            }
            questions_detail.append(question_detail)
        
        # 获取证书信息
        certificate = exam_record.certificates.first() if exam_record.certificates else None
        
        result = {
            'exam_id': exam.id,
            'exam_title': exam.title,
            'score': exam_record.score,
            'total_score': exam.total_score,
            'pass_score': exam.pass_score,
            'is_passed': exam_record.is_passed,
            'start_time': exam_record.start_time.isoformat(),
            'end_time': exam_record.end_time.isoformat() if exam_record.end_time else None,
            'duration': exam_record.duration,
            'total_questions': len(questions_detail),
            'correct_count': sum(1 for q in questions_detail if q['is_correct']),
            'questions': questions_detail,
            'certificate': certificate.to_dict() if certificate else None
        }
        
        return success_response(result)
    except Exception as e:
        logger.error(f"获取考试结果失败: {e}")
        return error_response('获取考试结果失败', 500)

@exams_bp.route('/<int:exam_id>/start', methods=['POST'])
@user_required
def start_exam(exam_id):
    """开始考试"""
    try:
        exam = Exam.query.filter_by(id=exam_id, is_active=True).first()
        if not exam:
            return error_response('试卷不存在', 404)
        
        current_user_id = get_jwt_identity()
        
        # 检查是否已有进行中的考试
        ongoing_exam = ExamRecord.query.filter_by(
            user_id=current_user_id,
            exam_id=exam_id,
            end_time=None
        ).first()
        
        if ongoing_exam:
            return error_response('您有进行中的考试，请先完成', 400)
        
        # 创建考试记录
        exam_record = ExamRecord(
            user_id=current_user_id,
            exam_id=exam_id,
            start_time=datetime.utcnow()
        )
        
        db.session.add(exam_record)
        db.session.commit()
        
        # 获取考试题目（不包含正确答案）
        questions = exam.get_questions_for_exam()
        
        return success_response({
            'exam_record_id': exam_record.id,
            'exam': {
                'id': exam.id,
                'title': exam.title,
                'time_limit': exam.time_limit,
                'total_score': exam.total_score
            },
            'questions': questions
        })
        
    except Exception as e:
        logger.error(f"开始考试失败: {e}")
        return error_response('开始考试失败', 500)

@exams_bp.route('/<int:exam_id>/submit', methods=['POST'])
@user_required
def submit_exam(exam_id):
    """提交考试答案"""
    try:
        data = request.get_json()
        exam_record_id = data.get('exam_record_id')
        answers = data.get('answers', {})
        
        if not exam_record_id:
            return error_response('考试记录ID不能为空', 400)
        
        current_user_id = get_jwt_identity()
        
        # 获取考试记录
        exam_record = ExamRecord.query.filter_by(
            id=exam_record_id,
            user_id=current_user_id,
            exam_id=exam_id
        ).first()
        
        if not exam_record:
            return error_response('考试记录不存在', 404)
        
        if exam_record.end_time:
            return error_response('考试已结束', 400)
        
        # 保存答案
        exam_record.answers = answers
        
        # 完成考试
        score = exam_record.finish_exam()
        
        # 更新排行榜
        from app.models import Leaderboard
        Leaderboard.update_user_stats(current_user_id, 'all_time')
        
        # 返回考试结果
        result = {
            'exam_record_id': exam_record.id,
            'score': score,
            'is_passed': exam_record.is_passed,
            'total_score': exam_record.exam.total_score,
            'pass_score': exam_record.exam.pass_score,
            'answers': {}
        }
        
        # 添加答题详情
        for eq in exam_record.exam.exam_questions:
            question = eq.question
            user_answer = answers.get(str(question.id))
            is_correct = question.check_answer(user_answer) if user_answer else False
            
            result['answers'][str(question.id)] = {
                'user_answer': user_answer,
                'correct_answer': question.correct_answer,
                'is_correct': is_correct,
                'score': eq.score if is_correct else 0
            }
        
        return success_response(result)
        
    except Exception as e:
        logger.error(f"提交考试失败: {e}")
        return error_response('提交考试失败', 500)

@exams_bp.route('/records', methods=['GET'])
@user_required
def get_user_exam_records():
    """获取用户的考试记录"""
    try:
        current_user_id = get_jwt_identity()
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        
        query = ExamRecord.query.filter_by(user_id=current_user_id)
        
        pagination = query.order_by(ExamRecord.created_at.desc()).paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )
        
        records = []
        for record in pagination.items:
            record_dict = record.to_dict()
            record_dict['exam'] = record.exam.to_dict()
            records.append(record_dict)
        
        return paginated_response(
            records,
            page,
            per_page,
            pagination.total
        )
        
    except Exception as e:
        logger.error(f"获取考试记录失败: {e}")
        return error_response('获取考试记录失败', 500)

# 管理员接口
@exams_bp.route('/admin/', methods=['GET'])
@admin_required
def admin_get_exams():
    """管理员获取试卷列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        is_active = request.args.get('is_active', type=lambda v: v.lower() == 'true')
        
        query = Exam.query
        
        if is_active is not None:
            query = query.filter_by(is_active=is_active)
        
        pagination = query.order_by(Exam.created_at.desc()).paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )
        
        return paginated_response(
            [exam.to_dict() for exam in pagination.items],
            page,
            per_page,
            pagination.total
        )
        
    except Exception as e:
        logger.error(f"管理员获取试卷列表失败: {e}")
        return error_response('获取试卷列表失败', 500)

@exams_bp.route('/admin/', methods=['POST'])
@admin_required
def create_exam():
    """创建试卷"""
    try:
        data = request.get_json()
        title = data.get('title')
        description = data.get('description', '')
        total_score = data.get('total_score', 100)
        pass_score = data.get('pass_score', 60)
        time_limit = data.get('time_limit', 30)
        question_count = data.get('question_count', 10)
        question_ids = data.get('question_ids', [])
        
        if not title:
            return error_response('试卷标题不能为空', 400)
        
        current_admin_id = int(get_jwt_identity().split('_')[1])
        
        exam = Exam(
            title=title,
            description=description,
            total_score=total_score,
            pass_score=pass_score,
            time_limit=time_limit,
            question_count=question_count,
            created_by=current_admin_id
        )
        
        db.session.add(exam)
        db.session.flush()  # 获取exam.id
        
        # 添加题目到试卷
        for i, question_id in enumerate(question_ids):
            question = Question.query.get(question_id)
            if question:
                from app.models.exam import ExamQuestion
                exam_question = ExamQuestion(
                    exam_id=exam.id,
                    question_id=question_id,
                    sort_order=i + 1,
                    score=total_score // len(question_ids)  # 平均分配分数
                )
                db.session.add(exam_question)
        
        db.session.commit()
        
        # 记录操作日志
        OperationLog.log_operation(
            action='create_exam',
            description=f'创建试卷: {title}',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam.id
        )
        
        return success_response(exam.to_dict(), '试卷创建成功')
        
    except Exception as e:
        logger.error(f"创建试卷失败: {e}")
        return error_response('创建试卷失败', 500)

@exams_bp.route('/admin/<int:exam_id>', methods=['PUT'])
@admin_required
def update_exam(exam_id):
    """更新试卷"""
    try:
        exam = Exam.query.get(exam_id)
        if not exam:
            return error_response('试卷不存在', 404)
        
        data = request.get_json()
        title = data.get('title')
        description = data.get('description')
        total_score = data.get('total_score')
        pass_score = data.get('pass_score')
        time_limit = data.get('time_limit')
        question_count = data.get('question_count')
        is_active = data.get('is_active')
        
        if title is not None:
            exam.title = title
        if description is not None:
            exam.description = description
        if total_score is not None:
            exam.total_score = total_score
        if pass_score is not None:
            exam.pass_score = pass_score
        if time_limit is not None:
            exam.time_limit = time_limit
        if question_count is not None:
            exam.question_count = question_count
        if is_active is not None:
            exam.is_active = is_active
        
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='update_exam',
            description=f'更新试卷: {exam.title}',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam.id
        )
        
        return success_response(exam.to_dict(), '试卷更新成功')
        
    except Exception as e:
        logger.error(f"更新试卷失败: {e}")
        return error_response('更新试卷失败', 500)

@exams_bp.route('/admin/records', methods=['GET'])
@admin_required
def admin_get_exam_records():
    """管理员获取考试记录"""
    print('admin_get_exam_records')
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        user_id = request.args.get('user_id', type=int)
        exam_id = request.args.get('exam_id', type=int)
        is_passed = request.args.get('is_passed', type=lambda v: v.lower() == 'true')
        
        query = ExamRecord.query
        
        print('user_id:',user_id)
        print('page:',page)
        print('per_page:',per_page)
        print('exam_id:',exam_id)
        print('is_passed:',is_passed)
        
        if user_id:
            query = query.filter_by(user_id=user_id)
        if exam_id:
            query = query.filter_by(exam_id=exam_id)
        if is_passed is not None:
            query = query.filter_by(is_passed=is_passed)
        
        pagination = query.order_by(ExamRecord.created_at.desc()).paginate(
            page=page,
            per_page=per_page,
            error_out=False
        )
        
        records = []
        for record in pagination.items:
            record_dict = record.to_dict()
            record_dict['exam'] = record.exam.to_dict()
            record_dict['user'] = record.user.to_dict()
            records.append(record_dict)
            
        return paginated_response(
            records,
            page,
            per_page,
            pagination.total
        )
        
    except Exception as e:
        logger.error(f"管理员获取考试记录失败: {e}")
        return error_response('获取考试记录失败', 500) 
    

@exams_bp.route('/admin/<int:exam_id>/questions', methods=['GET'])
@admin_required
def get_exam_questions(exam_id):
    
    """获取考试题目"""
    try:
        exam = Exam.query.get(exam_id)
        if not exam:
            return error_response('考试不存在', 404)
        
        exam_questions = exam.get_questions()
        questions = []
        
        for eq in exam_questions:
            question_dict = eq.question.to_dict()
            question_dict['sort_order'] = eq.sort_order
            question_dict['score'] = eq.score
            questions.append(question_dict)
        
        return success_response(questions)
        
    except Exception as e:
        logger.error(f"获取考试题目失败: {e}")
        return error_response('获取考试题目失败', 500)

@exams_bp.route('/admin/<int:exam_id>/questions', methods=['POST'])
@admin_required
def add_exam_questions(exam_id):
    """添加题目到考试"""
    try:
        exam = Exam.query.get(exam_id)
        if not exam:
            return error_response('考试不存在', 404)
        
        data = request.get_json()
        question_ids = data.get('question_ids', [])
        score = data.get('score', 10)
        
        if not question_ids:
            return error_response('请选择要添加的题目', 400)
        
        from app.models.exam import ExamQuestion
        
        # 获取当前最大排序号
        max_sort_order = db.session.query(db.func.max(ExamQuestion.sort_order)).filter_by(exam_id=exam_id).scalar() or 0
        
        added_count = 0
        for question_id in question_ids:
            # 检查题目是否存在
            question = Question.query.get(question_id)
            if not question:
                continue
                
            # 检查是否已经添加过
            existing = ExamQuestion.query.filter_by(exam_id=exam_id, question_id=question_id).first()
            if existing:
                continue
            
            # 添加题目
            exam_question = ExamQuestion(
                exam_id=exam_id,
                question_id=question_id,
                sort_order=max_sort_order + added_count + 1,
                score=score
            )
            db.session.add(exam_question)
            added_count += 1
        
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='add_exam_questions',
            description=f'向考试 {exam.title} 添加了 {added_count} 道题目',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam_id
        )
        
        return success_response(None, f'成功添加 {added_count} 道题目')
        
    except Exception as e:
        logger.error(f"添加考试题目失败: {e}")
        return error_response('添加考试题目失败', 500)

@exams_bp.route('/admin/<int:exam_id>/questions/<int:question_id>', methods=['DELETE'])
@admin_required
def delete_exam_question(exam_id, question_id):
    """从考试中删除题目"""
    try:
        from app.models.exam import ExamQuestion
        
        exam_question = ExamQuestion.query.filter_by(exam_id=exam_id, question_id=question_id).first()
        if not exam_question:
            return error_response('题目不存在', 404)
        
        db.session.delete(exam_question)
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='delete_exam_question',
            description=f'从考试中删除题目 {question_id}',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam_id
        )
        
        return success_response(None, '题目删除成功')
        
    except Exception as e:
        logger.error(f"删除考试题目失败: {e}")
        return error_response('删除考试题目失败', 500)

@exams_bp.route('/admin/<int:exam_id>/publish', methods=['POST'])
@admin_required
def publish_exam(exam_id):
    """发布考试"""
    try:
        exam = Exam.query.get(exam_id)
        if not exam:
            return error_response('考试不存在', 404)
        
        # 检查是否有题目
        question_count = exam.exam_questions.count()
        if question_count == 0:
            return error_response('考试没有题目，无法发布', 400)
        
        # 检查总分是否大于0
        total_score = sum(eq.score for eq in exam.exam_questions)
        if total_score <= 0:
            return error_response('考试总分必须大于0', 400)
        
        # 更新考试状态
        exam.is_active = True
        exam.total_score = total_score
        exam.question_count = question_count
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='publish_exam',
            description=f'发布考试: {exam.title}',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam_id
        )
        
        return success_response(exam.to_dict(), '考试发布成功')
        
    except Exception as e:
        logger.error(f"发布考试失败: {e}")
        return error_response('发布考试失败', 500)

@exams_bp.route('/admin/<int:exam_id>/questions/update', methods=['POST'])
@admin_required
def update_exam_questions(exam_id):
    """批量更新考试题目的顺序和分值"""
    try:
        from app.models.exam import ExamQuestion
        data = request.get_json()
        updates = data.get('updates', [])
        
        for item in updates:
            eq = ExamQuestion.query.filter_by(exam_id=exam_id, question_id=item['question_id']).first()
            if eq:
                eq.sort_order = item.get('sort_order', eq.sort_order)
                eq.score = item.get('score', eq.score)
        
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='update_exam_questions',
            description=f'更新考试题目顺序和分值',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam_id
        )
        
        return success_response(None, '题目顺序和分值已更新')
        
    except Exception as e:
        logger.error(f"更新考试题目失败: {e}")
        return error_response('更新考试题目失败', 500)

@exams_bp.route('/admin/<int:exam_id>', methods=['DELETE'])
@admin_required
def delete_exam(exam_id):
    """删除考试"""
    try:
        exam = Exam.query.get(exam_id)
        if not exam:
            return error_response('考试不存在', 404)
        
        # 检查是否有考试记录
        if exam.exam_records.count() > 0:
            return error_response('该考试已有考试记录，无法删除', 400)
        
        db.session.delete(exam)
        db.session.commit()
        
        # 记录操作日志
        current_admin_id = int(get_jwt_identity().split('_')[1])
        OperationLog.log_operation(
            action='delete_exam',
            description=f'删除考试: {exam.title}',
            admin_id=current_admin_id,
            resource_type='exam',
            resource_id=exam_id
        )
        
        return success_response(None, '考试删除成功')
        
    except Exception as e:
        logger.error(f"删除考试失败: {e}")
        return error_response('删除考试失败', 500)